home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 1996 September / Software of the Month Club 1996 September.iso / mac / Software Research Institute-SRI / Business / Alpha ƒ / Tcl / SystemCode / procs.tcl < prev    next >
Encoding:
Text File  |  1996-01-07  |  23.9 KB  |  960 lines  |  [TEXT/ALFA]

  1.  
  2. #==============================================================================
  3. # Load electric alias, rebind tcl file completion for precedence.
  4. proc loadElectricAlias {} {
  5.     global HOME
  6.     uplevel #0 {
  7.         source "$HOME:Tcl:ElectricAlias:electricAlias.tcl"
  8.     }
  9.     message "ElectricAlias loaded."
  10.     bind '\t' tclFileCompletion "Shel"
  11.     enableMenuItem -m install "Electric Alias" off
  12. }
  13.  
  14. proc debug {} {
  15.     uplevel #0 {
  16.         set debugging 1
  17.     }
  18. }
  19.  
  20.  
  21. proc normalLeftBracket {} {
  22.     insertText "\{"
  23. }
  24. proc normalRightBracket {} {
  25.     insertText "\}"
  26. }
  27. bind '\[' <zs>  normalLeftBracket
  28. bind '\]' <zs>  normalRightBracket
  29.             
  30. # Select the next or current word. If word already selected, will go to next.
  31. proc hiliteWord {} {
  32.     if {[getPos]!=[selEnd]}    forwardChar
  33.     forwardWord
  34.     set start [getPos]
  35.     backwardWord
  36.     select $start [getPos]
  37. }
  38.  
  39. bind 'h' <z> hiliteWord
  40.  
  41. #================================================================================
  42. # Mode variables
  43. #================================================================================
  44. # For mark stack.
  45. set markName 0
  46. set markStack ""
  47.  
  48. # mapping of windows to current modes.
  49. set winModes("") ""
  50.  
  51. # making vars local to windows
  52. # 'incomingVars' used to hold old var values that have been overwritten in current window
  53.  
  54. #================================================================================
  55. # Handle 'flag' and 'var' menu selections.
  56. #================================================================================
  57. proc editFlag {menu item} {
  58.     global $item incomingVars localVars modifiedVars tcl_var_procs
  59.  
  60.     if {[regexp {\? (.*)} $item dummy var]} {
  61.         alphaHelp
  62.         eval select [search -f 1 -r 1 "^$var"]
  63.         return
  64.     }
  65.     lappend modifiedVars $item
  66.     set val [expr ([set $item]-1)*-1]
  67.     markMenuItem $menu $item [expr ($val)?"on":"off"]
  68.     set $item $val
  69.  
  70.     if {[info exists tcl_var_procs($item)]} {
  71.         $tcl_var_procs($item) $item
  72.     }
  73. }
  74.  
  75. proc editVar {menu item} {
  76.     global $item incomingVars localVars modifiedVars
  77.  
  78.     if {[regexp {\? (.*)} $item dummy var]} {
  79.         alphaHelp
  80.         eval select [search -f 1 -r 1 "^$var"]
  81.         return
  82.     }
  83.     lappend modifiedVars $item
  84.     append prmpt "New Value of " $item ": "
  85.     if ![catch {prompt $prmpt [set $item]} res] {
  86.         set $item $res
  87.     }
  88. }
  89.  
  90.  
  91.  
  92.  
  93. #================================================================================
  94.  
  95. # Instantiate a global variable to the path of a file (usually an app). As a
  96. # side-effect, make the instantiation permanent.
  97. proc addAppPath {name var} {
  98.     global $var modifiedVars
  99.     
  100.     if {$name == "CodeWarrior Compiler"} {
  101.         alertnote {Please locate the compiler via menu item "Mode:App Paths:CodeWarrior Compiler"}
  102.         error ""
  103.     } elseif {$name == "CodeWarrior Debugger"} {
  104.         alertnote {Please locate the debugger via menu item "Mode:App Paths:CodeWarrior Debugger"}
  105.         error ""
  106.     }
  107.         
  108.     set $var [getfile "Find '$name' app:"]
  109.     lappend modifiedVars $var
  110. }
  111.  
  112.  
  113. proc getFileSig {f} {
  114.     getFileInfo $f arr
  115.     return $arr(creator)
  116. }
  117.  
  118. proc getFileType {f} {
  119.     getFileInfo $f arr
  120.     return $arr(type)
  121. }
  122.  
  123.  
  124. # Look for given app sig in active processes. If not there, try to 
  125. # launch with 'path' prompting for 'path' if necessary.
  126. # Return the real name of the app. Don't switch.
  127.  
  128. # Slightly modified version of 'checkRunning' that looks for any of a
  129. # list of running apps.  The name of the app is returned. 
  130. proc checkRunning {prompt sigs path {in_front 1}} {
  131.     global $path
  132.  
  133.     # See if a process w/ any of the acceptable sigs already running.
  134.     # If so, use it, whether it's the one specified by $path or not.
  135.     #
  136.     foreach proc [processes] {
  137.         # if a running app has the correct sig, ...
  138.         if {[lsearch -exact $sigs [lindex $proc 1]] >= 0} {
  139.             # ...then return its name.
  140.             return [lindex $proc 0]
  141.         }
  142.     }
  143.  
  144.     # If the path variable or the file it references don't exist,
  145.     # or if its sig isn't one that we expect, then prompt the user 
  146.     # to locate the app.
  147.     #
  148.     if {![info exists $path] || ![file exists [set $path]] 
  149.              || [lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  150.         if {[catch {addAppPath $prompt $path}]} return
  151.     }
  152.  
  153.     # Check that the user's choice has an acceptable sig
  154.     if {[lsearch -exact $sigs [getFileSig [set $path]]] < 0} {
  155.         unset $path
  156.         message "Inappropriate file chosen"
  157.         return {} 
  158.     }
  159.     
  160.     # Launch the app
  161.     if {$in_front} {
  162.         if {[catch {launch -f [set $path]}]} {
  163.             error "Problem with launching file (out of memory?)"
  164.         }
  165.     } else {
  166.         if {[catch {launch [set $path]}]} {
  167.             error "Problem with launching file (out of memory?)"
  168.         }
  169.     }        
  170.     
  171.     # Return the name of the chosen application
  172.     return [file tail [set $path]]
  173. }
  174.  
  175.  
  176. #================================================================================
  177. # Excalibur is the only Mac spell-checker that I know of which will handle LaTeX as
  178. # well as ordinary text.
  179.  
  180.  
  181. proc spellcheckWindow {} {
  182.     global excaliburPath resumeRevert
  183.  
  184.     catch {checkRunning Excalibur XCLB excaliburPath} name
  185.  
  186.     if {[winDirty]} {
  187.         if {[askyesno "Save '[lindex [winNames] 0]'?"] == "yes"} {
  188.             save
  189.         }
  190.     }
  191.     sendOpenEvent noReply $name [lindex [winNames -f] 0]
  192.     switchTo $name
  193.     set resumeRevert 1
  194. }
  195.  
  196. proc spellcheckSelection {} {
  197.     global excaliburPath 
  198.  
  199.     catch {checkRunning Excalibur XCLB excaliburPath} name
  200.  
  201.     if {[getPos] == [selEnd]} {
  202.         beep
  203.         message "No selection"
  204.         return;
  205.     }
  206.     copy
  207.     switchTo $name
  208. }
  209.  
  210. #================================================================================
  211.  
  212.  
  213. proc alphaHelp {} {
  214.     global HOME alphaLite
  215.     if $alphaLite {
  216.         edit -r "$HOME:Help:Quick Start"
  217.     } else {
  218.         edit -r "$HOME:Help:Manual"
  219.     }
  220. }
  221.  
  222.  
  223. proc tclHelp {} {
  224.     global HOME
  225.     edit -r "$HOME:Help:Tcl Commands"
  226. }
  227.  
  228.  
  229. proc dividingLine {} {
  230.     insertText "===============================================================================\r"
  231. }
  232. bind 'l' <C> dividingLine
  233.  
  234. proc texDividingLine {} {
  235.     insertText "%===============================================================================\r"
  236. }
  237. bind 'l' <C> texDividingLine TeX
  238.  
  239. proc cDividingLine {} {
  240.     insertText "//===============================================================================\r"
  241. }
  242. bind 'l' <C> cDividingLine C
  243. bind 'l' <C> cDividingLine C++
  244.  
  245. proc tclDividingLine {} {
  246.     insertText "#===============================================================================\r"
  247. }
  248. bind 'l' <C> tclDividingLine Tcl
  249.  
  250.  
  251. #================================================================================
  252.  
  253. if {![string length [info commands oldCd]]} {
  254.     rename cd oldCd
  255. }
  256.  
  257. proc cd args {
  258.     global HOME
  259.     if {[llength $args]} {
  260.         oldCd [string trim [eval list $args] "        \{\}"]
  261.     } else {
  262.         oldCd $HOME
  263.     }
  264. }
  265.  
  266.  
  267.  
  268. #############################################################################
  269. #  List the name and value of each element of the array $arrName.
  270. #  (Convenient to use as a shell command.)
  271. #
  272. #  Note: it's slower to insert the lines one-by-one like this, but 
  273. #  assembling everything in $lines before inserting can seriously crash Alpha
  274. #  if the result is too big.  (Trying to list the contents of $auto_index()
  275. #  will do it.)  This method seems to be more robust.
  276. #
  277. proc listArray {arrName} {
  278.     global $arrName
  279.     set lines {}
  280.     if {![catch {info vars $arrName}]} {
  281.         foreach nm [array names $arrName] {
  282.             set val [expr \$$arrName\($nm\)]
  283.             append lines "\r\"$nm\"\t\{$val\}"
  284.         }
  285.         insertText $lines
  286.     } else {
  287.         alertnote "\"$arrName\" doesn't exist in this context"
  288.     }
  289. }
  290.  
  291.  
  292.  
  293. #================================================================================
  294.     
  295. proc selectParagraph {} {
  296.     set pos [getPos]
  297.     set start [paraStart $pos] 
  298.     set finish [paraFinish $pos]
  299.     goto $start
  300.     select $start $finish
  301. }
  302.  
  303. # wrapText ==  getText ; breakIntoLines ; replaceText
  304. # Remove text from window, transform (join, del-ws), insert back into window.
  305. proc fillTextByPar {from to} {
  306.     set text [getText $from $to]
  307.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  308.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  309.     regsub -all "\[ \t\]+" $text " " text
  310.     return [breakIntoLines $text]
  311. }
  312.  
  313. proc fillRegionByPar {{start -1} {finish -1}} {
  314. #    # if {[getPos] == [selEnd]} { return}
  315.     if {($start < 0) || ($finish < 0)} {
  316.         set start [lineStart [getPos]]
  317.         set finish [selEnd] }
  318.     if {$start >= $finish} return
  319.     goto $start
  320.     set text [fillTextByPar $start $finish]
  321.     replaceText $start $finish $text "\r"
  322. }
  323.     
  324. #
  325. # join Lines in region -- if no optional args, use selection
  326. #
  327. proc joinRegion {{from -1} {to -1}} {
  328.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  329.     if {$from >= $to} return
  330.     set text [getText $from $to]
  331.     regsub -all "\r(\[ \t\]*\r)+" $text "\r\r\r" text
  332.     regsub -all "(\[^\r\])\r" $text "\\1 " text
  333.     replaceText $from $to $text "\r"
  334. }
  335. # WARNING:    regsub ^$ refers to string endpts (not lines)
  336. # FUTURE:    filterLines like perl:
  337. #    replaceText[apply_to_all(cmd,split [getText [getPos] [selEnd]] "\r")]
  338. # OR:    replaceInRegion: dup_\r, $=>\r ??
  339. #
  340.  
  341.  
  342. #
  343. # Remove text from window, transform (delete dup ws), insert back into window.
  344. #
  345. # inputs: message, alertnote, askyesno, listpick, prompt KILLS SELECTION.
  346. # search: bnds = search -forward -regExpr -ignoreCase -matchWords -noabort 
  347. #        -l limit pat pos
  348. proc regsubInRegion {from to srch repl} {
  349.     if {![string length $srch]} return
  350.     if {$from >= $to} return
  351.     set text [getText $from $to]
  352.     regsub -all "$srch" $text "$repl" text
  353.     replaceText $from $to $text
  354. }
  355. #    while {($pos < $to) &&
  356. #          ![catch {search -s -f 1 -r 1 -i 1 -m 0 "$srch" $pos} mtch]} {
  357. #        set mbeg [lindex $mtch 0]
  358. #        set pos [lindex $mtch 1]
  359. #        replaceText $mbeg $pos $repl }
  360.  
  361. #proc backSlashSub {arg} { eval [concat return "\"$arg\""] }
  362.  
  363. proc backSlashSub {arg} {
  364.     regsub -all {\\} $arg {\\\\} arg
  365.     regsub -all {\[} $arg {\\[} arg
  366.     regsub -all {\]} $arg {\\]} arg
  367.     eval [concat return "\"$arg\""]
  368. }
  369.  
  370. proc replaceInRegion {} {
  371.     if [catch {prompt "Search RegExpr:" ""} srch] return
  372.     if [catch {prompt "Replace String:" ""} repl] return
  373.     if {![string length $srch]} return
  374.     regsubInRegion [getPos] [selEnd] \
  375.         [backSlashSub "$srch"] [backSlashSub "$repl"]
  376. }
  377.  
  378. #
  379. # Apply command to each line (or paragraph) in selection ;
  380. #    if no cmd arg then prompts for it
  381. #
  382. proc filterLines {{cmd 0} {parunit 0}} {
  383.     if {$cmd == 0} {
  384.       if {[catch { prompt "Line-filter command: " "" } cmd]} { return } }
  385.     if {![string length $cmd]} return
  386.     set unitStart lineStart
  387.     set unitEnd nextLineStart
  388.     if {$parunit} {
  389.         set unitStart paraStart
  390.         set unitEnd paraFinish }
  391.     set pos [$unitStart [getPos]]
  392.     set finish [selEnd]
  393.     if {$pos >= $finish} return
  394.     goto $pos
  395.     createTMark "filterLend" $finish
  396.     set next [$unitEnd $pos]
  397.     while {(($next > $pos) && ($pos < $finish))} {
  398.         goto [expr $next-1]
  399.         createTMark "filterLnext" $next
  400.         setMark
  401.         goto $pos
  402.         markHilite
  403.         if {[catch [list uplevel #0 "$cmd"] retval]} {
  404.             select $pos $finish
  405.             alertnote $retval
  406.             return
  407.         }
  408.         if {$next==$finish} break
  409.         set ind [lsearch -regexp [lindex [getTMarks] 0] "filterLend.*"]
  410.         set finish [lindex [lindex [lindex [getTMarks] 0] $ind] 2]
  411.         gotoTMark "filterLnext"
  412.         set pos [$unitStart [getPos]]
  413.         set next [$unitEnd $pos]
  414.     }
  415.     removeTMark "filterLend"
  416.     removeTMark "filterLnext"
  417. }
  418.  
  419.  
  420. proc filterParagraphs {{cmd 0}} { filterLines $cmd 1 }
  421.  
  422. # WARNING: deselecting sets the mark to selEnd
  423. proc sortParagraphs {{from -1} {to -1}} {
  424.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  425.     if {$from >= $to} return
  426.     joinRegion {$from $to}
  427.     select [getPos] [nextLineStart [getMark]]
  428.     sortLines
  429.     select [getPos] [getPos]
  430.     regsubInRegion [getPos] [getMark] "\r" "\r\r" 
  431.     wrapRegion
  432. }
  433.  
  434. #
  435. # Sample
  436. #
  437. proc filterRegion {{from -1} {to -1} {cmd 0} {newwin 0}} {
  438.     if {$cmd == 0} {
  439.       if {[catch { prompt "Eval command: " "" } cmd]} { return }
  440.     }
  441.     if {![string length $cmd]} return
  442.     if {($from < 0) || ($to < 0)} {    set from [getPos] ; set to [selEnd] }
  443.     if {$from >= $to} return
  444.     set pos [getPos]
  445.     set text [getText $from $to]
  446.     set text [$cmd $text]
  447.     replaceText $from $to $text "\r"
  448.     goto $pos
  449. }
  450.  
  451.  
  452. #
  453. set lastEvaled ""
  454. proc evaluate {} {
  455.     global lastEvaled
  456.     if {[string length $lastEvaled]} {
  457.         set p "M-x ($lastEvaled): "
  458.     } else {
  459.         set p "M-x: "
  460.     }
  461.     if {[catch {statusPrompt $p} text]} {return}
  462.     if {![string length $text]} {set text $lastEvaled}
  463.     $text
  464.     set lastEvaled $text
  465. }
  466.  
  467.  
  468. # First, define macros to bypass the electric braces.
  469. proc ordLeftBrace {} {
  470.     insertText "        \{"
  471. }
  472. bind {'['} <cs> ordLeftBrace
  473.  
  474. proc ordRightBrace {} {
  475.     insertText "\}"
  476.     blink [matchIt "\}" [expr [getPos]-1]]
  477. }
  478. bind {']'} <cs> ordRightBrace
  479.     
  480. proc quoteWord {} {
  481.     backwardWord
  482.     insertText "'"
  483.     forwardWord
  484.     insertText "'"
  485. }
  486. bind ''' <z> quoteWord
  487.  
  488. #================================================================================
  489.  
  490. proc tomac {fname} {
  491.     set fd [open $fname "r"]
  492.     set text [read $fd]
  493.     close $fd
  494.     set fd [open $fname "w"]
  495.     regsub "\n" $text "\r" text
  496.     puts -nonewline $fd $text
  497.     close $fd
  498. }
  499.  
  500. proc tounix {fname} {
  501.     set fd [open $fname "r"]
  502.     set text [read $fd]
  503.     close $fd
  504.     set fd [open $fname "w"]
  505.     regsub "\r" $text "\n" text
  506.     puts -nonewline $fd $text
  507.     close $fd
  508. }
  509.  
  510.  
  511. proc cat args {
  512.     set files ""
  513.     foreach a $args {
  514.         foreach f [glob $a] {
  515.             lappend files $f
  516.         }
  517.     }
  518.     foreach f $files {
  519.         append text "==============<$f>==============\r"
  520.         set fd [open $f "r"]
  521.         append text "[read $fd]\r\r"
  522.         close $fd
  523.     }
  524.     return $text
  525. }
  526.  
  527. proc catto args {
  528.     set len [llength $args]
  529.     set to [lindex $args [expr $len -1]]
  530.     set args [lrange $args 0 [expr $len -2]]
  531.  
  532.     set files ""
  533.     foreach a $args {
  534.         foreach f [glob $a] {
  535.             lappend files $f
  536.         }
  537.     }
  538.     foreach f $files {
  539.         append text "==============<$f>==============\r"
  540.         set fd [open $f "r"]
  541.         append text "[read $fd]\r\r"
  542.         close $fd
  543.     }
  544.  
  545.     set dfile $to
  546.     if {[file exists $dfile]} {
  547.         set fid [open $dfile "a"]
  548.     } else {
  549.         set fid [open $dfile "w"]
  550.     }
  551.     puts $fid $text
  552.     close $fid
  553. }
  554.  
  555.  
  556. ##############################################################################
  557. #  To be used in the windows created by "matchingLines" or by batch searches.
  558. #
  559. #  With the cursor positioned in a line corrsponding to a match, 
  560. #  go back and select the line in the original file that 
  561. #  generated this match.  (Like emacs 'Occur' functionality)
  562. #
  563. proc gotoMatch {} {
  564.     if {[string match "*MAILBOX*" [lindex [winNames] 0]]} {
  565.         mailGotoMatch
  566.         return
  567.     }
  568.     global tileHeight tileWidth tileTop tileLeft tileHeight errorHeight errorDisp tileMargin
  569.     set errorDisp [expr (2 * ($tileHeight - $tileMargin)) / 3]
  570.     set text [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
  571.     set ind1 [string first "░" $text]
  572.     set ind2 [string last "░" $text]
  573.     if {$ind1 == $ind2} {
  574.         set fname [string trim [string range $text $ind1 end] {░}]
  575.         set msg ""
  576.     } else {
  577.         set fname [string trim [string range $text $ind1 $ind2] {░}]
  578.         set msg [string trim [string range $text $ind2 end] {░}]
  579.     }
  580.     
  581.     set top $tileTop
  582.     set geo [getGeometry]
  583.     if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 3] != $errorHeight) } {
  584.         moveWin $tileLeft $top
  585.         sizeWin $tileWidth $errorHeight
  586.     }
  587.     set mar $tileMargin
  588.     incr top [expr $errorHeight + $mar]
  589.     if {[expr {[lsearch [winNames -f] "*$fname"] >= 0}]} {
  590.         if {[string match ":*" $fname]} {
  591.             set fname [file tail $fname]
  592.         }
  593.         bringToFront $fname
  594.         set geo [getGeometry]
  595.         if {([lindex $geo 0] != $tileLeft) || ([lindex $geo 1] != $top) || ([lindex $geo 2] != $tileWidth) || ([lindex $geo 3] != $errorDisp) } {
  596.             sizeWin $tileWidth $errorDisp
  597.             moveWin $tileLeft $top
  598.         }
  599.     } elseif {[file exists $fname]} {
  600.         edit -g $tileLeft $top $tileWidth $errorDisp $fname
  601.     } else {
  602.         if {![string match "*Link*" [getText 0 [nextLineStart 0]]]} {
  603.             alertnote "File \" $fname \" not found." 
  604.         }
  605.         return
  606.     }
  607.     if {[regexp {Line ([0-9]+):} $text dummy line]} {
  608.         set pos [rowColToPos $line 0]
  609.         select $pos [nextLineStart $pos]
  610.     }
  611.     message $msg
  612. }
  613. bind 'c' <Cz>        gotoMatch
  614.  
  615.  
  616. #================================================================================
  617.  
  618. proc prevIntro {} {
  619.     set res [search -s -f 0 -r 0 {== } [getPos]]
  620.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  621. }
  622.  
  623. proc nextIntro {} {
  624.     set res [search -s -f 1 -r 0 {== } [getPos]]
  625.     set res [lindex $res 1]
  626.     set res [search -s -f 1 -r 0 {== } $res]
  627.     display [lineStart [expr [lineStart [lindex $res 0]] - 1]]
  628. }
  629.  
  630. #================================================================================
  631.  
  632. proc searchStart {} {
  633.     global search_start
  634.     select [getPos]
  635.     setMark
  636.     if {[catch {goto $search_start}]} {message "No previous search"}
  637. }
  638.  
  639. #================================================================================
  640.  
  641.  
  642. proc listBindings {} {
  643.     new -n {* Key Bindings *}
  644.     insertText [bindingList]
  645.  
  646.     goto 0
  647.     setWinInfo dirty 0
  648.     setWinInfo read-only 1
  649. }
  650.  
  651.  
  652. proc listFunctions {} {
  653.     global winModes
  654.     new -n {* Functions *}
  655.     insertText "===\r\tCommand-double-click on a function to see its definition\r===\r\r" [join [lsort -ignore [info commands]] "\r"] "\r"
  656.     goto 0
  657.     setWinInfo dirty 0
  658.     changeMode [set winModes([lindex [winNames] 0]) Tcl]
  659. }
  660.  
  661.  
  662. #================================================================================
  663.  
  664. proc printArray {arr} {
  665.     global $arr
  666.         foreach n [array names $arr] {
  667.         append text "$n '[set ${arr}($n)]'\r"
  668.     }
  669.     return [string trim $text "\r"]
  670. }
  671.  
  672. #================================================================================
  673.  
  674.  
  675. proc doATab {} {
  676.     global mode
  677.     global ${mode}modeVars
  678.     if {[info exists ${mode}modeVars] && ![set ${mode}modeVars(electricTab)] || [regexp {[^ \t]} [getText [lineStart [getPos]] [getPos]]]} {
  679.         if {[getPos] != [selEnd]} {
  680.             replaceText [getPos] [selEnd] "\t"
  681.         } else {
  682.             insertText "\t"
  683.         }
  684.     } else {
  685.         indentLine
  686.     }
  687. }
  688.  
  689. #     set ptext [getText [lindex $lst 0] [nextLineStart [lindex $lst 0]]]
  690. #     regsub -all {[^(]} $ptext {} one
  691. #     regsub -all {[^)]} $ptext {} two
  692. #     if {[string length $one] > [string length $two]} {
  693. #         regexp {[^(]*\(} $ptext blah
  694. #         regsub -all {[^    ]} $blah { } lwhite
  695. #     } elseif {($nextC == "\{")} {
  696. #         append lwhite "\t"
  697. #     }
  698.  
  699. # proc indentLine {} {
  700. #     global mode
  701. #     
  702. #     set beg [lineStart [getPos]]
  703. #     set lst [search -s -f 0 -r 1 -i 0 {^[ \t]*[^ \t\r]} [expr $beg-1]]
  704. #     set lwhite [getText [lindex $lst 0] [expr [lindex $lst 1] - 1]]
  705. #     set nextC [lookAt [expr [nextLineStart [lindex $lst 1]] - 2]]
  706. #     if {($nextC == "\{")} {
  707. #         append lwhite "\t"
  708. #     } elseif {$nextC == ":"} {
  709. #         set lwhite "[string range $lwhite 0 [expr [string length $lwhite]-3]]\t"
  710. #     }
  711. #         
  712. #     set text [getText $beg [nextLineStart $beg]]
  713. #     regexp {^[ \t]*} $text white
  714. #     set len [string length $white]
  715. #     set nextC [lookAt [expr $beg + $len]]
  716. #     if {$nextC == "\}"} {
  717. #         set lwhite [string range $lwhite 0 [expr [string length $lwhite] - 2]]
  718. #     }
  719. #     
  720. #     global ${mode}modeVars
  721. #     if {[string match "*:\r" $text] && [info exists ${mode}modeVars(elecColon)] && [set ${mode}modeVars(elecColon)]} {
  722. #         if {[string index $lwhite 0] == "\t"} {
  723. #             set lwhite "[string range $lwhite 1 [expr [string length $lwhite] - 1]]  "
  724. #         }
  725. #     }
  726. #     if {$white != $lwhite} {
  727. #         replaceText $beg [expr $beg + $len] $lwhite
  728. #     }
  729. #     goto [expr $beg + [string length $lwhite]]
  730. # }
  731.  
  732.  
  733. proc indentRegion {} {
  734.     set from [lindex [posToRowCol [getPos]] 0]
  735.     set to [lindex [posToRowCol [selEnd]] 0]
  736.     select [getPos]
  737.     while {$from <= $to} {
  738.         goto [rowColToPos $from 0]
  739.         indentLine
  740.         incr from
  741.     }
  742. }
  743.  
  744. #================================================================================
  745.  
  746. proc sPrompt {msg def} {
  747.     global useStatusBar
  748.     if {!$useStatusBar} {return [prompt $msg $def]}
  749.     if {[catch {statusPrompt "$msg ($def): "} ans]} {
  750.         error "cancel"
  751.     }
  752.     if {![string length $ans]} {return $def}
  753.     return $ans
  754. }
  755.  
  756. #================================================================================
  757. proc quoteChar {} {
  758.     message "Literal keystroke to be inserted:"
  759.     insertText [getChar]
  760. }
  761. #===============================================================================
  762.  
  763. proc saveACopyAs {} {
  764.     if {[file exists [set nm [lindex [winNames -f] 0]]]} {
  765.         set nm2 [putfile "Save a copy as:" [file tail $nm]]
  766.         cp $nm $nm2
  767.     }
  768. }
  769. #===============================================================================
  770. proc removeDups {l} {
  771.     foreach f $l {
  772.         set silly($f) 1
  773.     }
  774.     if {[info exists silly]} {
  775.         return [array names silly]
  776.     }
  777. }
  778.             
  779.  
  780. #===============================================================================
  781.  
  782. proc printHeaderProc {} {
  783.     global printHeader printHeaderTime printHeaderFullPath
  784.     
  785.     if {!$printHeader} return ""
  786.     
  787.     if {$printHeaderFullPath} {
  788.         set text [lindex [winNames -f] 0]
  789.     } else {
  790.         set text [lindex [winNames] 0]
  791.     }
  792.     
  793.     if {$printHeaderTime} {
  794.         append text "      [join [mtime [now] short]]"
  795.     }
  796. }
  797.  
  798. #===============================================================================
  799.  
  800. proc toggleNumLock {} {
  801.     global numLock modifiedVars
  802.     
  803.     set numLock [expr -1 * ($numLock - 1)]
  804.     lappend modifiedVars numLock
  805. }
  806.  
  807. #===============================================================================
  808.  
  809. proc register {} {
  810.     global HOME
  811. #    edit -r "$HOME:Help:Registering"
  812.     launch -f "$HOME:Register 1.1.5 Keleher"
  813. }
  814.  
  815. #===============================================================================
  816. # Useful for -command flag of 'lsort'.
  817. proc sortByTail {one two} {
  818.     string compare [file tail $one] [file tail $two]
  819. }
  820.  
  821.  
  822. #===============================================================================
  823.  
  824. proc cmdDoubleClick {{from -1} {to -1} {shift 0} {option 0} {control 0}} {
  825.     global  mode
  826.     
  827.     if {[string length [set whe [expandURL]]]} {
  828.         sendUrl [getSelect]
  829.     } else {
  830.         if {$from < 0} {
  831.             set from [getPos]
  832.             set to [selEnd]
  833.             if {$from == $to} {
  834.                 message "No selection"
  835.                 return
  836.             }
  837.         }
  838.         
  839.         if {[string length [info commands ${mode}DblClick]]} {
  840.             if {[llength [info args ${mode}DblClick]] == 2} {
  841.                 ${mode}DblClick $from $to
  842.             } else {
  843.                 ${mode}DblClick $from $to $shift $option $control
  844.             }
  845.         } else {
  846.             message "No docs"
  847.         }
  848.     }    
  849. }
  850.  
  851. #===============================================================================
  852.  
  853.  
  854. proc editMark {fname mname args} {
  855.     if {[set pos [lsearch [winNames -f] "*$fname*"]] >= 0}  {
  856.         bringToFront [lindex [winNames -f] $pos]
  857.     } else {
  858.         if {[lsearch $args {-r}] >= 0} {
  859.             edit -r "$fname"
  860.         } else {
  861.             edit "$fname"
  862.         }
  863.     }
  864.     if {[lsearch [getNamedMarks -n] $mname] < 0} {
  865.         global    mode
  866.         ${mode}MarkFile
  867.     } 
  868.     gotoMark $mname
  869. }
  870.  
  871.  
  872. proc winDirty {} {
  873.     getWinInfo arr
  874.     return $arr(dirty)
  875. }
  876.  
  877.  
  878. #===============================================================================
  879.  
  880. proc lreverse {l} {
  881.     if {[llength $l] > 1} {
  882.         set first [lindex $l 0]
  883.         set l [lreverse [lrange $l 1 end]]
  884.         lappend l $first
  885.     }
  886.     return $l
  887. }
  888.  
  889.     
  890. #===============================================================================
  891.  
  892.  
  893. set {patternLibrary(Pascal to C Comments)}      { {\{([^\}]*)\}}    {/* \1 */}     }
  894. set {patternLibrary(C++ to C Comments)}            { {//(.*)}            {/* \1 */}     }
  895. set {patternLibrary(Space Runs to Tabs)}        { { +}                {\t}         }
  896.  
  897.  
  898.  
  899. proc getPatternLibrary {} {
  900.     global patternLibrary
  901.     
  902.     foreach nm [array names patternLibrary] {
  903.         lappend nms [concat [list $nm] $patternLibrary($nm)]
  904.     }
  905.     return $nms
  906. }
  907.  
  908. proc rememberPatternHook {search replace} {
  909.     global patternLibrary
  910.     if {[catch {set name [prompt "New pattern's name?" ""]}]} {
  911.         return ""
  912.     }
  913.     addArrDef patternLibrary $name [list $search $replace]
  914.     set patternLibrary($name) [list $search $replace]
  915.     return $name
  916. }
  917.  
  918. proc deletePatternHook {} {
  919.     global patternLibrary
  920.     
  921.     
  922.     set temp [list prompt "Delete which pattern?" [lindex [array names patternLibrary] 0] "Pats:"]
  923.     set name [eval [concat $temp [array names patternLibrary]]]
  924.     removeArrDef patternLibrary $name
  925.     unset patternLibrary($name)
  926. }
  927.  
  928. #===============================================================================
  929. # Support for Peter Gontier's 'ClickWarrior' (Doesn't work for 68k).
  930. #===============================================================================
  931.  
  932. eventHandler ALFA CWOF clickHandler
  933.  
  934. proc clickHandler {msg} {
  935.     global HOME ALPHA dum CODEWarrior CWCLASS
  936.     switchTo $ALPHA
  937.     checkCw
  938.     if {[regexp {╥(.*)╙.*╟.*╚.*╟(.*)╚.*╟(.*)╚} $msg dummy fname find sind]} {
  939.         set res [AEBuild -t 500000 -r $CODEWarrior $CWCLASS GFil "----" "long(╟0000$find╚)" Segm "long($sind)"]
  940.         if {[regexp {FTxt} $res]} {
  941.             regexp {╟(.*)╚} $res dummy spec
  942.             set f [specToPathName $spec]
  943.             edit $f
  944.         }
  945.     }
  946. }
  947.  
  948. #===============================================================================
  949. proc quickFind {} {isearch}
  950. proc reverseQuickFind {} {rsearch}
  951.  
  952. proc pushPosition {} {pushMark}
  953. proc popPosition {} {popMark}
  954. #===============================================================================
  955.